﻿using mozhi.smarterp.Business.Enums;
using mozhi.smarterp.Business.Products.Repositories;
using mozhi.smarterp.Business.Purchases.Repositories;
using Mozhi.Abp.Domain.BasicData.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Domain.Services;
using Volo.Abp.Guids;

namespace mozhi.smarterp.Business.Purchases.Services
{
    public class PurchaseRequisitionOrderManager : DomainService
    {
        private IPurchaseRequisitionOrderRepository _repository;
        private IPurchaseRequisitionRepository _requisitionRepository;
        private PurchaseOrderManager _purchaseOrderManager;
        private IProductPurchaseSettingRepository _productPurchaseSettingRepository;
        private IEmployeeRepository _employeeRepository;
        private INumberGeneratorRepository _numberGeneratorRepository;
        private IGuidGenerator _guidGenerator;

        public PurchaseRequisitionOrderManager(IPurchaseRequisitionOrderRepository repository, IPurchaseRequisitionRepository requisitionRepository,
            IProductPurchaseSettingRepository productPurchaseSettingRepository, IEmployeeRepository employeeRepository, INumberGeneratorRepository numberGeneratorRepository,
            PurchaseOrderManager purchaseOrderManager , IGuidGenerator guidGenerator)
        {
            _repository = repository;
            _requisitionRepository = requisitionRepository;
            _productPurchaseSettingRepository = productPurchaseSettingRepository;
            _employeeRepository = employeeRepository;
            _numberGeneratorRepository = numberGeneratorRepository;

            _purchaseOrderManager = purchaseOrderManager;
            _guidGenerator = guidGenerator;
        }

        /// <summary>
        /// 采购申请单整单下推
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="UserFriendlyException"></exception>
        public async Task<Tuple<List<PurchaseOrder>, List<PurchaseRequisitionOrder>>> GetPurchaseOrdersFromRequisitionAsync(Guid id)
        {
            var requisition = await _requisitionRepository.GetAsync(id);

            if (requisition == null)
                throw new UserFriendlyException("申请单不存在", "100000");

            if (requisition.Status != DocumentStatusType.Approved)
                throw new UserFriendlyException("申请单不是审核状态，不能生成采购订单", "100000");


            var requisitionItems = requisition.Items.Where(x => x.SuggestedSupplierId.HasValue).ToList();

            if (requisitionItems.Count == 0)
                throw new UserFriendlyException("申请单的分录都没有建议供应商，无法生成采购订单", "100000");

            var requisitionOrders = await _repository.GetListAsync(requisition.Id, null, null, null);

            var associated‌RequisitionItemIds = requisitionOrders.Select(x => x.RequisitionItemId).ToList();

            requisitionItems = requisitionItems.Where(x => !associatedRequisitionItemIds.Contains(x.Id)).ToList();

            if (requisitionItems.Count == 0)
                throw new UserFriendlyException("申请单分录已经全部生成采购订单", "100000");

            var productIds = requisitionItems.Select(x => x.ProductId).Distinct().ToList();

            var productPurchaseSettings = await _productPurchaseSettingRepository.GetListAsync(productIds);

            var groups = requisitionItems.GroupBy(x => new { x.SuggestedSupplierId, x.RequiredDate });

            var orders = new List<PurchaseOrder>();

            requisitionOrders = new List<PurchaseRequisitionOrder>();

            //没有设置采购员的产品
            List<Guid> notSettingPurchaserProductIds = new List<Guid>();

            string currentNumber = null;

            foreach (var group in groups)
            {
                var supplierId = group.Key.SuggestedSupplierId;

                var requiredDate = group.Key.RequiredDate ?? DateTime.UtcNow;

                var tempRequisitionItems = group.ToList();

                foreach (var requisitionItem in tempRequisitionItems)
                {
                    var matchProductSetting = productPurchaseSettings.FirstOrDefault(x => x.ProductId == requisitionItem.ProductId);

                    var purchaser = matchProductSetting == null ? null : await _employeeRepository.GetAsync(matchProductSetting.DefaultPurchaserId);

                    var order = orders.FirstOrDefault(x => x.SupplierId == supplierId && x.RequiredDate == requiredDate && x.DepartmentId == purchaser.DepartmentId && x.PurchaserId == purchaser.Id);

                    if (order == null)
                    {
                        //如果不为空，表示前面已经去过编号了，下一个订单，需要在原来的编号基础上获取编号
                        currentNumber = currentNumber.IsNullOrEmpty() ? currentNumber : (await _numberGeneratorRepository.GetAsync((int)DocumentType.PurchaseOrder, currentNumber)).Number;

                        order = await _purchaseOrderManager.GetAysnc(null, purchaser?.DepartmentId, DateTime.UtcNow, requiredDate, currentNumber, null,
                            PurchaseOrderType.Standard, null, requisition.CurrencyId, requisition.ExchangeRate, requisition.IncludeTax, purchaser?.Id, requisitionItem.SuggestedSupplierId);

                        currentNumber = order.Number;
                    }


                    var orderItem = await _purchaseOrderManager.GetItemsAsync(null, requisitionItem.ProductId, requisitionItem.AuxiliaryUnitId, requisitionItem.ApprovedQuantity, requisitionItem.Price, false, requisitionItem.TaxRateId, "");

                    var orderItems = new List<PurchaseOrderItem>();

                    orderItems.AddRange(order.Items);
                    orderItems.Add(orderItem);

                    order.ChangeItems(orderItems);

                    if (!orders.Exists(x => x.Id == order.Id))
                        orders.Add(order);

                    requisitionOrders.Add(new PurchaseRequisitionOrder(_guidGenerator.Create(), requisition.Id, requisitionItem.Id, requisitionItem.BasicQuantity , order.Id, orderItem.Id , orderItem.BasicQuantity));
                }
            }

            return new Tuple<List<PurchaseOrder>, List<PurchaseRequisitionOrder>>(orders , requisitionOrders);
        }
    }
}
